﻿using System;

namespace ZL.Web.Utility
{
    public static class CodeValidate
    {

        public static string GetValidatecode(string wxcardno)
        {
            int sum = 0;
            foreach (char item in wxcardno)
            {
                int td = (int)item;
                sum += td;
            }
            string sumstr = sum.ToString();
            sumstr = sumstr.Substring(sumstr.Length - 1, 1);
            return sumstr;
        }

        /// <summary>
        /// 产生验算码
        /// </summary>
        /// <param name="pmcardno"></param>
        /// <param name="cardssid">卡种</param>
        /// <param name="cardcudsid">折扣类别</param>
        /// <param name="pmVailidDate"></param>
        /// <returns></returns>
        public static string GenCodeforCRMPhyCard(string pmcardno, string cardssid, string cardcudsid, DateTime pmVailidDate)
        {
            TimeSpan ts = pmVailidDate - new DateTime(2000, 1, 1, 0, 0, 0, 0);
            string diff = Convert.ToInt64(ts.Days).ToString();
            int Issid = DecimalConvert.ConvertTo10(cardssid);
            int Icardcudsid = DecimalConvert.ConvertTo10(cardcudsid);
            string Sssid = SupZore(Issid);
            string Scardcudsid = SupZore(Icardcudsid);
            int first = int.Parse(Sssid[0].ToString());
            int second = int.Parse(Sssid[1].ToString());
            int three = int.Parse(Scardcudsid[0].ToString());
            int forth = int.Parse(Scardcudsid[1].ToString());
            string scard = CRC32Cls.GetCRC32Str(diff + "|" + pmcardno+ "|" + Sssid + "|" + Scardcudsid).ToString();
            scard = SupZore(ref scard);
            int result = Sum(first, second, three, forth, scard);
            int[] Poses = PickPos(result);
            string[] sds = new string[14];
            sds[Poses[0]] = first.ToString();
            sds[Poses[1]] = second.ToString();
            sds[Poses[2]] = three.ToString();
            sds[Poses[3]] = forth.ToString();
            int j = 0;
            for (int i = 0; i < 14; i++)
            {
                if (string.IsNullOrEmpty(sds[i]))
                {
                    sds[i] = scard[j].ToString();
                    j++;
                }
            }
            string resultstr= string.Join("", sds);
            return resultstr;
        }

        public static Tuple<bool, string,string> GenCodeforCRMPhyCard1(string pmcardno, string validatecode, DateTime pmVailidDate)
        {
            try
            {
                int result = Sums(validatecode);
                int[] Poses = PickPos(result);

                string Sssid = validatecode[Poses[0]].ToString() + validatecode[Poses[1]].ToString();
                string Scardcudsid = validatecode[Poses[2]].ToString() + validatecode[Poses[3]].ToString();
                string[] sds = new string[10];
                int j = 0;
                for (int i = 0; i < 14; i++)
                {
                    if (i != Poses[0] && i != Poses[1] && i != Poses[2] && i != Poses[3])
                    {
                        sds[j] = validatecode[i].ToString();
                        j++;
                    }
                }
                string cardno = string.Join("", sds);
                string Issid = DecimalConvert.ConvertTo36(int.Parse(Sssid));
                string Icardcudsid = DecimalConvert.ConvertTo36(int.Parse(Scardcudsid));
                TimeSpan ts = pmVailidDate - new DateTime(2000, 1, 1, 0, 0, 0, 0);
                string diff = Convert.ToInt64(ts.Days).ToString();
                string scard = CRC32Cls.GetCRC32Str(diff + "|" + pmcardno + "|" + Sssid + "|" + Scardcudsid).ToString();
                scard = SupZore(ref scard);
                Tuple<bool, string, string> sd = new Tuple<bool, string, string>(scard == cardno, Issid, Icardcudsid);
                return sd;
            }
            catch (Exception)
            {

                Tuple<bool, string, string> error = new Tuple<bool, string, string>(false,"","");
                return error;
            }
        }

        private static int Sums(string scard)
        {
            int innersum = 0;
            foreach (char ditgter in scard)
            {
                innersum += int.Parse(ditgter.ToString());
            }
            return innersum;
        }


        /// <summary>
        /// 位置组随机数
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        private static int[] PickPos(int result)
        {
            switch (result)
            {
                case 0:
                    return new int[4] { 3, 5, 11, 10, };
                case 1:
                    return new int[4] { 6, 8, 3, 4, };
                case 2:
                    return new int[4] { 8, 6, 0, 13, };
                case 3:
                    return new int[4] { 0, 3, 10, 11, };
                case 4:
                    return new int[4] { 9, 3, 2, 8, };
                case 5:
                    return new int[4] { 10, 7, 4, 13, };
                case 6:
                    return new int[4] { 11, 12, 0, 10, };
                case 7:
                    return new int[4] { 0, 8, 3, 11, };
                case 8:
                    return new int[4] { 2, 1, 3, 0, };
                case 9:
                    return new int[4] { 12, 13, 5, 4, };
                case 10:
                    return new int[4] { 4, 2, 1, 8, };
                case 11:
                    return new int[4] { 4, 1, 8, 6, };
                case 12:
                    return new int[4] { 3, 6, 12, 2, };
                case 13:
                    return new int[4] { 13, 9, 3, 12, };
                case 14:
                    return new int[4] { 1, 11, 10, 3, };
                case 15:
                    return new int[4] { 6, 13, 2, 8, };
                case 16:
                    return new int[4] { 0, 4, 9, 8, };
                case 17:
                    return new int[4] { 2, 9, 12, 8, };
                case 18:
                    return new int[4] { 1, 10, 12, 8, };
                case 19:
                    return new int[4] { 12, 0, 3, 9, };
                case 20:
                    return new int[4] { 11, 2, 10, 0, };
                case 21:
                    return new int[4] { 10, 8, 6, 11, };
                case 22:
                    return new int[4] { 5, 7, 4, 13, };
                case 23:
                    return new int[4] { 12, 11, 4, 7, };
                case 24:
                    return new int[4] { 0, 12, 9, 5, };
                case 25:
                    return new int[4] { 12, 10, 1, 13, };
                case 26:
                    return new int[4] { 2, 3, 8, 5, };
                case 27:
                    return new int[4] { 10, 13, 12, 6, };
                case 28:
                    return new int[4] { 6, 13, 8, 10, };
                case 29:
                    return new int[4] { 1, 3, 2, 0, };
                case 30:
                    return new int[4] { 2, 3, 11, 8, };
                case 31:
                    return new int[4] { 4, 13, 11, 2, };
                case 32:
                    return new int[4] { 11, 0, 1, 10, };
                case 33:
                    return new int[4] { 9, 6, 11, 5, };
                case 34:
                    return new int[4] { 3, 0, 5, 1, };
                case 35:
                    return new int[4] { 3, 0, 7, 10, };
                case 36:
                    return new int[4] { 0, 10, 13, 6, };
                case 37:
                    return new int[4] { 0, 11, 2, 10, };
                case 38:
                    return new int[4] { 2, 12, 10, 11, };
                case 39:
                    return new int[4] { 13, 5, 6, 7, };
                case 40:
                    return new int[4] { 10, 13, 11, 1, };
                case 41:
                    return new int[4] { 0, 6, 10, 8, };
                case 42:
                    return new int[4] { 0, 1, 12, 2, };
                case 43:
                    return new int[4] { 3, 13, 0, 12, };
                case 44:
                    return new int[4] { 10, 7, 9, 13, };
                case 45:
                    return new int[4] { 13, 5, 12, 3, };
                case 46:
                    return new int[4] { 7, 4, 11, 5, };
                case 47:
                    return new int[4] { 2, 6, 11, 7, };
                case 48:
                    return new int[4] { 10, 4, 3, 8, };
                case 49:
                    return new int[4] { 12, 13, 5, 6, };
                case 50:
                    return new int[4] { 11, 9, 3, 6, };
                case 51:
                    return new int[4] { 3, 1, 13, 11, };
                case 52:
                    return new int[4] { 12, 2, 6, 5, };
                case 53:
                    return new int[4] { 11, 1, 9, 6, };
                case 54:
                    return new int[4] { 1, 8, 7, 10, };
                case 55:
                    return new int[4] { 0, 1, 4, 2, };
                case 56:
                    return new int[4] { 11, 10, 4, 0, };
                case 57:
                    return new int[4] { 10, 9, 5, 7, };
                case 58:
                    return new int[4] { 3, 4, 1, 13, };
                case 59:
                    return new int[4] { 12, 2, 1, 13, };
                case 60:
                    return new int[4] { 8, 13, 2, 3, };
                case 61:
                    return new int[4] { 10, 3, 5, 13, };
                case 62:
                    return new int[4] { 9, 7, 1, 5, };
                case 63:
                    return new int[4] { 5, 2, 13, 7, };
                case 64:
                    return new int[4] { 6, 9, 0, 11, };
                case 65:
                    return new int[4] { 8, 13, 10, 7, };
                case 66:
                    return new int[4] { 4, 10, 12, 11, };
                case 67:
                    return new int[4] { 12, 0, 5, 8, };
                case 68:
                    return new int[4] { 6, 12, 4, 11, };
                case 69:
                    return new int[4] { 13, 0, 12, 7, };
                case 70:
                    return new int[4] { 1, 6, 9, 11, };
                case 71:
                    return new int[4] { 7, 5, 1, 0, };
                case 72:
                    return new int[4] { 0, 2, 11, 12, };
                case 73:
                    return new int[4] { 6, 5, 9, 10, };
                case 74:
                    return new int[4] { 3, 10, 5, 1, };
                case 75:
                    return new int[4] { 1, 12, 9, 2, };
                case 76:
                    return new int[4] { 12, 6, 0, 1, };
                case 77:
                    return new int[4] { 4, 9, 6, 7, };
                case 78:
                    return new int[4] { 13, 0, 8, 9, };
                case 79:
                    return new int[4] { 7, 4, 2, 0, };
                case 80:
                    return new int[4] { 4, 10, 8, 3, };
                case 81:
                    return new int[4] { 2, 10, 13, 11, };
                case 82:
                    return new int[4] { 3, 6, 5, 7, };
                case 83:
                    return new int[4] { 8, 13, 12, 11, };
                case 84:
                    return new int[4] { 9, 4, 3, 0, };
                case 85:
                    return new int[4] { 6, 9, 12, 3, };
                case 86:
                    return new int[4] { 4, 0, 9, 6, };
                case 87:
                    return new int[4] { 5, 3, 8, 11, };
                case 88:
                    return new int[4] { 13, 7, 0, 4, };
                case 89:
                    return new int[4] { 4, 1, 7, 9, };
                case 90:
                    return new int[4] { 8, 2, 0, 9, };
                case 91:
                    return new int[4] { 1, 2, 11, 12, };
                case 92:
                    return new int[4] { 12, 6, 7, 13, };
                case 93:
                    return new int[4] { 12, 13, 9, 7, };
                case 94:
                    return new int[4] { 9, 4, 11, 2, };
                case 95:
                    return new int[4] { 5, 1, 4, 2, };
                case 96:
                    return new int[4] { 8, 1, 7, 2, };
                case 97:
                    return new int[4] { 1, 4, 3, 10, };
                case 98:
                    return new int[4] { 10, 7, 3, 5, };
                case 99:
                    return new int[4] { 0, 11, 9, 6, };
                case 100:
                    return new int[4] { 5, 13, 1, 11, };
                case 101:
                    return new int[4] { 1, 13, 6, 10, };
                case 102:
                    return new int[4] { 0, 10, 6, 2, };
                case 103:
                    return new int[4] { 11, 1, 2, 6, };
                case 104:
                    return new int[4] { 10, 13, 4, 7, };
                case 105:
                    return new int[4] { 4, 6, 8, 2, };
                case 106:
                    return new int[4] { 13, 8, 3, 10, };
                case 107:
                    return new int[4] { 10, 8, 2, 13, };
                case 108:
                    return new int[4] { 8, 1, 2, 10, };
                case 109:
                    return new int[4] { 1, 3, 4, 9, };
                case 110:
                    return new int[4] { 2, 13, 5, 11, };
                case 111:
                    return new int[4] { 5, 13, 7, 6, };
                case 112:
                    return new int[4] { 12, 0, 6, 11, };
                case 113:
                    return new int[4] { 6, 10, 5, 1, };
                case 114:
                    return new int[4] { 6, 8, 13, 9, };
                case 115:
                    return new int[4] { 8, 2, 5, 3, };
                case 116:
                    return new int[4] { 2, 6, 5, 3, };
                case 117:
                    return new int[4] { 2, 3, 5, 7, };
                case 118:
                    return new int[4] { 9, 2, 1, 5, };
                case 119:
                    return new int[4] { 11, 0, 7, 1, };
                case 120:
                    return new int[4] { 13, 2, 5, 4, };
                case 121:
                    return new int[4] { 0, 6, 12, 5, };
                case 122:
                    return new int[4] { 8, 2, 4, 11, };
                case 123:
                    return new int[4] { 6, 1, 4, 11, };
                case 124:
                    return new int[4] { 11, 2, 8, 3, };
                case 125:
                    return new int[4] { 0, 8, 6, 10, };
                case 126:
                    return new int[4] { 4, 12, 2, 11, };
                default:
                    return new int[4] { 0, 0, 0, 0 };
            }
        }

        /// <summary>
        /// 14个数字求和
        /// </summary>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <param name="three"></param>
        /// <param name="forth"></param>
        /// <param name="scard"></param>
        /// <returns></returns>
        private static int Sum(int first, int second, int three, int forth, string scard)
        {
            int innersum = 0;
            foreach (char ditgter in scard)
            {
                innersum += int.Parse(ditgter.ToString());
            }
            int sum = innersum + first + second + three + forth;
            return sum;
        }

        /// <summary>
        /// 折扣类别卡种补0
        /// </summary>
        /// <param name="icardcudsid"></param>
        /// <returns></returns>
        private static string SupZore(int icardcudsid)
        {
            if (icardcudsid < 10)
            {
                return string.Format("0{0}", icardcudsid);
            }
            return icardcudsid.ToString();
        }

        /// <summary>
        /// 卡号摘要不满10位部0
        /// </summary>
        /// <param name="icardcudsid"></param>
        /// <returns></returns>
        private static string SupZore(ref string icardcudsid)
        {
            if (icardcudsid.Length == 10) return icardcudsid;
            if (icardcudsid.Length < 10)
            {
                icardcudsid= icardcudsid.Insert(0, "0");
                SupZore(ref icardcudsid);
            }
            return icardcudsid;
        }
    }
}
